package com.cyan.note.service.manager.impl;

import com.cyan.note.common.ApiResult;
import com.cyan.note.common.ResultCode;
import com.cyan.note.dto.manager.dashboard.*;
import com.cyan.note.mapper.*;
import com.cyan.note.service.manager.ManagerDashboardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 店长端-工作台服务实现类
 * 
 * @author ZhangzhenYu
 * @since 2025-01-15
 */
@Service
@Slf4j
public class ManagerDashboardServiceImpl implements ManagerDashboardService {

    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private WorkerMapper workerMapper;
    
    @Autowired
    private CustomerMapper customerMapper;
    
    @Autowired
    private ServiceMapper serviceMapper;
    
    @Autowired
    private OrderLogMapper orderLogMapper;

    @Override
    public ApiResult<DashboardOverviewDTO> getDashboardOverview(Long shopId) {
        try {
            DashboardOverviewDTO overview = new DashboardOverviewDTO();
            
            // 获取今日和昨日统计  
            LocalDateTime today = LocalDate.now().atStartOfDay();
            
            OrderMapper.TodayStatsResult todayStats = orderMapper.selectTodayStats(shopId, today);
            
            // 订单统计
            overview.setTodayOrders(todayStats.getTodayOrders() != null ? todayStats.getTodayOrders() : 0);
            overview.setYesterdayOrders(todayStats.getYesterdayOrders() != null ? todayStats.getYesterdayOrders() : 0);
            overview.setOrderGrowthRate(calculateGrowthRate(overview.getTodayOrders(), overview.getYesterdayOrders()));
            
            // 营收统计
            overview.setTodayRevenue(todayStats.getTodayRevenue() != null ? todayStats.getTodayRevenue() : BigDecimal.ZERO);
            overview.setYesterdayRevenue(todayStats.getYesterdayRevenue() != null ? todayStats.getYesterdayRevenue() : BigDecimal.ZERO);
            overview.setRevenueGrowthRate(calculateGrowthRate(overview.getTodayRevenue(), overview.getYesterdayRevenue()));
            
            // 打手统计
            WorkerMapper.WorkerStatusOverview workerStatus = workerMapper.selectWorkerStatusOverview(shopId);
            Integer onlineWorkers = workerMapper.countOnlineWorkers(shopId);
            overview.setOnlineWorkers(onlineWorkers != null ? onlineWorkers : 0);
            overview.setTotalWorkers(workerStatus != null && workerStatus.getTotal() != null ? workerStatus.getTotal() : 0);
            overview.setOnlineRate(calculateRate(overview.getOnlineWorkers(), overview.getTotalWorkers()));
            
            // 客户统计
            CustomerMapper.CustomerStatsResult customerStats = customerMapper.selectCustomerStats(shopId);
            overview.setTotalCustomers(customerStats != null && customerStats.getTotalCount() != null ? customerStats.getTotalCount() : 0);
            overview.setActiveCustomers(customerStats != null && customerStats.getActiveCount() != null ? customerStats.getActiveCount() : 0);
            
            // 订单状态统计
            Integer pendingOrders = orderMapper.countPendingOrders(shopId);
            overview.setPendingOrders(pendingOrders != null ? pendingOrders : 0);
            
            // 计算其他指标
            overview.setActiveOrders(countActiveOrders(shopId));
            overview.setMonthlyRevenue(calculateMonthlyRevenue(shopId, LocalDate.now()));
            overview.setLastMonthRevenue(calculateMonthlyRevenue(shopId, LocalDate.now().minusMonths(1)));
            overview.setMonthlyGrowthRate(calculateGrowthRate(overview.getMonthlyRevenue(), overview.getLastMonthRevenue()));
            
            return ApiResult.success(overview);
        } catch (Exception e) {
            log.error("获取工作台概览失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取工作台概览失败");
        }
    }

    @Override
    public ApiResult<TodayStatsDTO> getTodayStats(Long shopId) {
        try {
            TodayStatsDTO stats = new TodayStatsDTO();
            
            LocalDateTime today = LocalDate.now().atStartOfDay();
            LocalDateTime tomorrow = today.plusDays(1);
            LocalDateTime yesterday = today.minusDays(1);
            
            // 构建查询参数
            Map<String, Object> todayParams = buildDateRangeParams(shopId, today, tomorrow);
            Map<String, Object> yesterdayParams = buildDateRangeParams(shopId, yesterday, today);
            
            // 今日统计
            com.cyan.note.dto.manager.order.OrderStatusStatsDTO todayOrderStats = orderMapper.selectOrderStatusStats(todayParams);
            com.cyan.note.dto.manager.order.OrderStatusStatsDTO yesterdayOrderStats = orderMapper.selectOrderStatusStats(yesterdayParams);
            
            // 设置今日数据
            stats.setNewOrders(todayOrderStats.getTotalCount() != null ? todayOrderStats.getTotalCount() : 0);
            stats.setCompletedOrders(todayOrderStats.getPaidCount() != null ? todayOrderStats.getPaidCount() : 0);
            stats.setCancelledOrders(todayOrderStats.getCancelledCount() != null ? todayOrderStats.getCancelledCount() : 0);
            stats.setRevenue(todayOrderStats.getTotalAmount() != null ? todayOrderStats.getTotalAmount() : BigDecimal.ZERO);
            stats.setReceivedAmount(todayOrderStats.getReceivedAmount() != null ? todayOrderStats.getReceivedAmount() : BigDecimal.ZERO);
            stats.setPendingAmount(todayOrderStats.getPendingAmount() != null ? todayOrderStats.getPendingAmount() : BigDecimal.ZERO);
            stats.setHourlyOrders(todayOrderStats.getHourlyOrderCount() != null ? todayOrderStats.getHourlyOrderCount() : 0);
            stats.setFixedOrders(todayOrderStats.getFixedOrderCount() != null ? todayOrderStats.getFixedOrderCount() : 0);
            stats.setAvgOrderAmount(todayOrderStats.getAvgOrderAmount() != null ? todayOrderStats.getAvgOrderAmount() : BigDecimal.ZERO);
            
            // 设置对比数据
            TodayStatsDTO.ComparisonData comparison = new TodayStatsDTO.ComparisonData();
            Integer yesterdayOrders = yesterdayOrderStats.getTotalCount() != null ? yesterdayOrderStats.getTotalCount() : 0;
            BigDecimal yesterdayRevenue = yesterdayOrderStats.getTotalAmount() != null ? yesterdayOrderStats.getTotalAmount() : BigDecimal.ZERO;
            
            comparison.setOrderGrowth(calculateGrowthRate(stats.getNewOrders(), yesterdayOrders));
            comparison.setRevenueGrowth(calculateGrowthRate(stats.getRevenue(), yesterdayRevenue));
            comparison.setIsPositive(comparison.getOrderGrowth().compareTo(BigDecimal.ZERO) >= 0);
            
            stats.setComparison(comparison);
            
            return ApiResult.success(stats);
        } catch (Exception e) {
            log.error("获取今日统计失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取今日统计失败");
        }
    }

    @Override
    public ApiResult<List<RevenueTrendDTO>> getRevenueTrend(Long shopId, Integer days) {
        try {
            LocalDateTime endDate = LocalDate.now().atTime(23, 59, 59);
            LocalDateTime startDate = endDate.minusDays(days - 1).toLocalDate().atStartOfDay();
            
            List<OrderMapper.RevenueTrendItem> trendItems = orderMapper.selectRevenueTrend(shopId, startDate, endDate);
            
            List<RevenueTrendDTO> trendList = trendItems.stream().map(item -> {
                RevenueTrendDTO dto = new RevenueTrendDTO();
                dto.setDate(item.getDate());
                dto.setRevenue(item.getRevenue() != null ? item.getRevenue() : BigDecimal.ZERO);
                dto.setOrderCount(item.getOrders() != null ? item.getOrders() : 0);
                dto.setAvgOrderAmount(dto.getOrderCount() > 0 ? 
                    dto.getRevenue().divide(BigDecimal.valueOf(dto.getOrderCount()), 2, RoundingMode.HALF_UP) : 
                    BigDecimal.ZERO);
                
                // 设置星期几
                LocalDate date = LocalDate.parse(item.getDate());
                dto.setDayOfWeek(getDayOfWeekName(date.getDayOfWeek().getValue()));
                
                return dto;
            }).collect(Collectors.toList());
            
            return ApiResult.success(trendList);
        } catch (Exception e) {
            log.error("获取营收趋势失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取营收趋势失败");
        }
    }

    @Override
    public ApiResult<WorkerStatusOverviewDTO> getWorkerStatusOverview(Long shopId) {
        try {
            WorkerStatusOverviewDTO overview = new WorkerStatusOverviewDTO();
            
            WorkerMapper.WorkerStatusOverview status = workerMapper.selectWorkerStatusOverview(shopId);
            
            overview.setTotalWorkers(status != null && status.getTotal() != null ? status.getTotal() : 0);
            overview.setIdleWorkers(status != null && status.getIdle() != null ? status.getIdle() : 0);
            overview.setWorkingWorkers(status != null && status.getWorking() != null ? status.getWorking() : 0);
            overview.setRestingWorkers(status != null && status.getRest() != null ? status.getRest() : 0);
            overview.setOfflineWorkers(status != null && status.getOffline() != null ? status.getOffline() : 0);
            overview.setOnlineWorkers(overview.getIdleWorkers() + overview.getWorkingWorkers() + overview.getRestingWorkers());
            
            overview.setOnlineRate(calculateRate(overview.getOnlineWorkers(), overview.getTotalWorkers()));
            overview.setWorkingRate(calculateRate(overview.getWorkingWorkers(), overview.getTotalWorkers()));
            
            return ApiResult.success(overview);
        } catch (Exception e) {
            log.error("获取打手状态概览失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取打手状态概览失败");
        }
    }

    @Override
    public ApiResult<List<ActiveOrderDTO>> getActiveOrders(Long shopId) {
        try {
            List<OrderMapper.ActiveOrderResult> activeOrders = orderMapper.selectActiveOrders(shopId);
            
            List<ActiveOrderDTO> dtoList = activeOrders.stream().map(order -> {
                ActiveOrderDTO dto = new ActiveOrderDTO();
                dto.setOrderId(order.getOrderId());
                dto.setOrderNo(order.getOrderNo());
                dto.setServiceName(order.getServiceName());
                dto.setCustomerName(order.getCustomerName());
                dto.setCustomerPhone(order.getCustomerPhone());
                dto.setStartTime(order.getStartTime());
                dto.setPlannedHours(order.getDurationHours());
                dto.setStatus(order.getStatus());
                dto.setStatusName(getOrderStatusName(order.getStatus()));
                
                // 计算已进行时长
                if (order.getStartTime() != null) {
                    long minutes = java.time.Duration.between(order.getStartTime(), LocalDateTime.now()).toMinutes();
                    dto.setElapsedMinutes((int) minutes);
                    
                    // 计算预计结束时间
                    if (order.getDurationHours() != null) {
                        dto.setExpectedEndTime(order.getStartTime().plusHours(order.getDurationHours().longValue()));
                        
                        // 判断是否超时
                        dto.setIsOvertime(LocalDateTime.now().isAfter(dto.getExpectedEndTime()));
                        if (dto.getIsOvertime()) {
                            long overtimeMinutes = java.time.Duration.between(dto.getExpectedEndTime(), LocalDateTime.now()).toMinutes();
                            dto.setOvertimeMinutes((int) overtimeMinutes);
                        }
                    }
                }
                
                return dto;
            }).collect(Collectors.toList());
            
            return ApiResult.success(dtoList);
        } catch (Exception e) {
            log.error("获取进行中订单失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取进行中订单失败");
        }
    }

    @Override
    public ApiResult<CustomerStatsDTO> getCustomerStats(Long shopId) {
        try {
            CustomerStatsDTO stats = new CustomerStatsDTO();
            
            CustomerMapper.CustomerStatsResult customerStats = customerMapper.selectCustomerStats(shopId);
            
            stats.setTotalCustomers(customerStats != null && customerStats.getTotalCount() != null ? customerStats.getTotalCount() : 0);
            stats.setActiveCustomers(customerStats != null && customerStats.getActiveCount() != null ? customerStats.getActiveCount() : 0);
            stats.setVipCustomers(customerStats != null && customerStats.getVipCount() != null ? customerStats.getVipCount() : 0);
            stats.setDebtCustomers(customerStats != null && customerStats.getDebtCount() != null ? customerStats.getDebtCount() : 0);
            
            stats.setActiveRate(calculateRate(stats.getActiveCustomers(), stats.getTotalCustomers()));
            
            return ApiResult.success(stats);
        } catch (Exception e) {
            log.error("获取客户统计失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取客户统计失败");
        }
    }

    @Override
    public ApiResult<List<ServiceStatsDTO>> getServiceStats(Long shopId, Integer days) {
        try {
            // 这里应该实现服务统计逻辑
            List<ServiceStatsDTO> serviceStats = new ArrayList<>();
            return ApiResult.success(serviceStats);
        } catch (Exception e) {
            log.error("获取服务统计失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取服务统计失败");
        }
    }

    @Override
    public ApiResult<List<AlertDTO>> getAlerts(Long shopId) {
        try {
            List<AlertDTO> alerts = new ArrayList<>();
            
            // 检查超时订单
            Integer overdueOrders = orderMapper.countOverdueOrders(shopId, 30);
            if (overdueOrders != null && overdueOrders > 0) {
                AlertDTO alert = new AlertDTO();
                alert.setAlertType(AlertDTO.AlertType.ORDER_TIMEOUT);
                alert.setLevel(AlertDTO.Level.HIGH);
                alert.setTitle("订单超时提醒");
                alert.setMessage(String.format("有 %d 个订单超过30分钟未分配", overdueOrders));
                alert.setAlertTime(LocalDateTime.now());
                alert.setIsHandled(false);
                alert.setUrgency(3);
                alerts.add(alert);
            }
            
            // 检查离线打手
            WorkerMapper.WorkerStatusOverview workerOverview = workerMapper.selectWorkerStatusOverview(shopId);
            Integer offlineWorkers = workerOverview != null && workerOverview.getOffline() != null ? workerOverview.getOffline() : 0;
            if (offlineWorkers > 5) {
                AlertDTO alert = new AlertDTO();
                alert.setAlertType(AlertDTO.AlertType.WORKER_OFFLINE);
                alert.setLevel(AlertDTO.Level.MEDIUM);
                alert.setTitle("打手离线提醒");
                alert.setMessage(String.format("有 %d 个打手处于离线状态", offlineWorkers));
                alert.setAlertTime(LocalDateTime.now());
                alert.setIsHandled(false);
                alert.setUrgency(2);
                alerts.add(alert);
            }
            
            return ApiResult.success(alerts);
        } catch (Exception e) {
            log.error("获取预警信息失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取预警信息失败");
        }
    }

    @Override
    public ApiResult<QuickActionsDTO> getQuickActions(Long shopId) {
        try {
            QuickActionsDTO actions = new QuickActionsDTO();
            
            Integer pendingOrdersCount = orderMapper.countPendingOrders(shopId);
            actions.setPendingOrdersCount(pendingOrdersCount != null ? pendingOrdersCount : 0);
            actions.setActiveOrdersCount(countActiveOrders(shopId));
            
            // 设置可用操作
            List<QuickActionsDTO.QuickAction> actionList = new ArrayList<>();
            
            QuickActionsDTO.QuickAction createOrder = new QuickActionsDTO.QuickAction();
            createOrder.setActionCode("create_order");
            createOrder.setActionName("手动下单");
            createOrder.setIcon("plus");
            createOrder.setUrl("/orders/create");
            createOrder.setEnabled(true);
            actionList.add(createOrder);
            
            actions.setAvailableActions(actionList);
            
            return ApiResult.success(actions);
        } catch (Exception e) {
            log.error("获取快速操作失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取快速操作失败");
        }
    }

    @Override
    public ApiResult<List<RecentActivityDTO>> getRecentActivities(Long shopId, Integer limit) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("limit", limit);
            
            List<com.cyan.note.entity.OrderLog> logs = orderLogMapper.selectByCondition(params);
            
            List<RecentActivityDTO> activities = logs.stream().map(log -> {
                RecentActivityDTO activity = new RecentActivityDTO();
                activity.setActivityId(log.getId());
                activity.setActivityType(log.getAction());
                activity.setTitle(getActivityTitle(log.getAction()));
                activity.setDescription(log.getDescription());
                activity.setOperatorName(log.getOperatorName());
                activity.setActivityTime(log.getCreatedAt());
                activity.setTimeDisplay(formatTimeDisplay(log.getCreatedAt()));
                return activity;
            }).collect(Collectors.toList());
            
            return ApiResult.success(activities);
        } catch (Exception e) {
            log.error("获取最近活动失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取最近活动失败");
        }
    }

    @Override
    public ApiResult<MonthlyReportDTO> getMonthlyReport(Long shopId, String month) {
        try {
            MonthlyReportDTO report = new MonthlyReportDTO();
            
            LocalDate reportMonth = month != null ? LocalDate.parse(month + "-01") : LocalDate.now().withDayOfMonth(1);
            LocalDateTime startTime = reportMonth.atStartOfDay();
            LocalDateTime endTime = reportMonth.plusMonths(1).atStartOfDay().minusSeconds(1);
            
            Map<String, Object> params = buildDateRangeParams(shopId, startTime, endTime);
            com.cyan.note.dto.manager.order.OrderStatusStatsDTO monthStats = orderMapper.selectOrderStatusStats(params);
            
            report.setMonth(reportMonth.format(DateTimeFormatter.ofPattern("yyyy-MM")));
            report.setTotalRevenue(monthStats.getTotalAmount() != null ? monthStats.getTotalAmount() : BigDecimal.ZERO);
            report.setTotalOrders(monthStats.getTotalCount() != null ? monthStats.getTotalCount() : 0);
            report.setCompletedOrders(monthStats.getPaidCount() != null ? monthStats.getPaidCount() : 0);
            report.setCancelledOrders(monthStats.getCancelledCount() != null ? monthStats.getCancelledCount() : 0);
            report.setCompletionRate(monthStats.getCompletionRate() != null ? monthStats.getCompletionRate() : BigDecimal.ZERO);
            report.setAvgOrderAmount(monthStats.getAvgOrderAmount() != null ? monthStats.getAvgOrderAmount() : BigDecimal.ZERO);
            
            return ApiResult.success(report);
        } catch (Exception e) {
            log.error("获取月度报告失败", e);
            return ApiResult.error(ResultCode.ERROR, "获取月度报告失败");
        }
    }

    @Override
    public ApiResult<Void> refreshDashboard(Long shopId) {
        try {
            // 这里可以实现缓存刷新逻辑
            return ApiResult.success();
        } catch (Exception e) {
            log.error("刷新工作台失败", e);
            return ApiResult.error(ResultCode.ERROR, "刷新工作台失败");
        }
    }

    // 私有辅助方法

    private BigDecimal calculateGrowthRate(Number current, Number previous) {
        if (previous == null || previous.doubleValue() == 0) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal currentValue = current instanceof BigDecimal ? (BigDecimal) current : BigDecimal.valueOf(current.doubleValue());
        BigDecimal previousValue = previous instanceof BigDecimal ? (BigDecimal) previous : BigDecimal.valueOf(previous.doubleValue());
        
        return currentValue.subtract(previousValue)
                .divide(previousValue, 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100));
    }

    private BigDecimal calculateRate(Integer numerator, Integer denominator) {
        if (denominator == null || denominator == 0) {
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(numerator != null ? numerator : 0)
                .divide(BigDecimal.valueOf(denominator), 4, RoundingMode.HALF_UP)
                .multiply(BigDecimal.valueOf(100));
    }

    private Integer countActiveOrders(Long shopId) {
        Map<String, Object> params = new HashMap<>();
        params.put("shopId", shopId);
        params.put("status", "in_progress");
        return orderMapper.countByCondition(params).intValue();
    }

    private BigDecimal calculateMonthlyRevenue(Long shopId, LocalDate month) {
        LocalDateTime startTime = month.withDayOfMonth(1).atStartOfDay();
        LocalDateTime endTime = month.plusMonths(1).withDayOfMonth(1).atStartOfDay();
        
        Map<String, Object> params = buildDateRangeParams(shopId, startTime, endTime);
        com.cyan.note.dto.manager.order.OrderStatusStatsDTO stats = orderMapper.selectOrderStatusStats(params);
        
        return stats.getTotalAmount() != null ? stats.getTotalAmount() : BigDecimal.ZERO;
    }

    private Map<String, Object> buildDateRangeParams(Long shopId, LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> params = new HashMap<>();
        params.put("shopId", shopId);
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        return params;
    }

    private String getDayOfWeekName(int dayOfWeek) {
        String[] dayNames = {"", "周一", "周二", "周三", "周四", "周五", "周六", "周日"};
        return dayNames[dayOfWeek];
    }

    private String getOrderStatusName(String status) {
        switch (status) {
            case "pending": return "待开始";
            case "assigned": return "已分配";
            case "in_progress": return "进行中";
            case "completed": return "未结账";
            case "paid": return "已付款";
            case "cancelled": return "已取消";
            default: return status;
        }
    }

    private String getActivityTitle(String action) {
        switch (action) {
            case "CREATE": return "创建订单";
            case "ASSIGN": return "分配订单";
            case "START": return "开始服务";
            case "COMPLETE": return "完成服务";
            case "PAYMENT": return "确认收款";
            case "CANCEL": return "取消订单";
            default: return "系统操作";
        }
    }

    private String formatTimeDisplay(LocalDateTime time) {
        LocalDateTime now = LocalDateTime.now();
        long minutes = java.time.Duration.between(time, now).toMinutes();
        
        if (minutes < 1) return "刚刚";
        if (minutes < 60) return minutes + "分钟前";
        if (minutes < 1440) return (minutes / 60) + "小时前";
        return (minutes / 1440) + "天前";
    }
}